<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\analysis\stat\account;

use app\enum\CdcEnum;
use app\model\mongo\MongoReportModel;
use app\model\mongo\MongoStatModel;
use app\service\cdc\AccountService;
use app\service\analysis\stat\StatService;
use app\service\cdc\sync\account\AccountLogService;
use app\service\stat\daily\AccountService as DayAccountService;
use app\service\stat\daily\ProductAccountTypeService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

abstract class AccountStatService extends StatService
{
    protected ?MongoStatModel $statModel;

    protected ?MongoReportModel $recordModel;

    /**
     * 初始化数据模型.
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function setModel(): bool
    {
        if (! $this->getRecordModel()) {
            return false;
        }

        if (! $this->getStatModel()) {
            return false;
        }

        return true;
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function getRecordModel()
    {
        if (! in_array($this->syncModel->getAttr('type'), array_keys($this->recordModelList))) {
            return self::setError('未知的统计类型');
        }

        $field = ['account_id', 'stat_date'];
        $where = [];
        foreach ($field as $v) {
            $where[] = [$v, '=', $this->syncModel->getAttr($v)];
        }

        $className = $this->recordModelList[$this->syncModel->getAttr('type')];
        $this->recordModel = (new $className())->where($where)->find();
        if (! $this->recordModel instanceof MongoReportModel) {
            $this->recordModel = new $className();
        }

        // 账户信息
        $accountInfo = \app\service\client\AccountService::getAccountModel($this->recordModel->getAttr('account_id'));
        // 账户端口信息
        $portInfo = (new DayAccountService())->getPort($this->recordModel->getAttr('adv_id'));

        // 销售信息
        $saleInfo = [];
        if ($accountInfo && $accountInfo->getAttr('account_type') > 0 && $portInfo && $portInfo->getAttr('product_id') > 0) {
            $saleInfo = (new ProductAccountTypeService())->getProductSalesman($portInfo->getAttr('product_id'), $this->mediaId, $accountInfo->getAttr('account_type'));
        }

        $statMonth = intval(mb_substr(strval($this->recordModel->getAttr('stat_date')), 0, 6));
        $this->recordModel->setAttrs([
            'media_id' => $this->mediaId,
            'account_type' => $accountInfo->getAttr('account_type') ?? 0,
            'stat_month' => $statMonth ?? 0,
            'product_id' => $portInfo['product_id'] ?? 0,
            'xs_id' => $saleInfo['xs_id'] ?? 0,
            'zl_id' => $saleInfo['zl_id'] ?? 0,
            'cost' => $this->recordModel->getCost(),
            'cash_cost' => $this->recordModel->getCashCost(),
            'reward_cost' => $this->recordModel->getRewardCost(),
            'balance' => $this->recordModel->getBalance(),
        ]);

        return $this->recordModel;
    }

    public function getStatModel()
    {
        if (! in_array($this->syncModel->getAttr('type'), array_keys($this->statModelList))) {
            return self::setError('未知的统计类型');
        }

        if ($this->syncModel->getAttr('type') == CdcEnum::STAT_CLIENT) {
            $fields = ['stat_date', 'client_id', 'account_type', 'media_id'];
        } elseif ($this->syncModel->getAttr('type') == CdcEnum::STAT_PRODUCT) {
            $fields = ['stat_date', 'product_id', 'account_type', 'media_id'];
        } elseif ($this->syncModel->getAttr('type') == CdcEnum::STAT_MONTH) {
            $fields = ['stat_month', 'client_id'];
        } else {
            $fields = ['stat_month', 'client_id', 'media_id'];
        }

        $where = [];
        foreach ($fields as $v) {
            if ($v == 'stat_month') {
                $statMonth = intval(date('Ym', strtotime(strval($this->syncModel->getAttr('stat_date')))));
                $where[] = [$v, '=', $statMonth];
            } elseif ($v == 'product_id') {
                $where[] = [$v, '=', $this->recordModel->getAttr($v)];
            } else {
                $where[] = [$v, '=', $this->syncModel->getAttr($v)];
            }
        }

        return $this->statModel = AccountService::getStatModel($this->mediaId, $this->syncModel->getAttr('type'), $where);
    }

    /*
    * 更新指定素材消耗.
    * @param Model $model 数据基础表模型
    */
    public function addStatByRecord(): bool
    {
        $fields = [];
        if (! $this->statModel->getKey()) {
            $fields = $this->getStatField();
        }

        if (! AccountService::addStat($this->statModel, $fields)) {
            return self::setError('更新统计数据失败');
        }

        if ($this->statModel->getKey()) {
            if (! $this->statModel->inc('cost', static::getCost())->update()) {
                return self::setError('更新统计数据失败');
            }
        }

        return AccountLogService::deleteLog($this->syncModel);
    }

    public function sumStat(): bool
    {
        if (! $this->statModel->getKey()) {
            $this->statModel->setAttrs($this->getSumStatField());
        }

        $statInfo = $this->getStatInfo();
        if (! $statInfo) {
            return self::setError('获取统计数据失败');
        }

        $this->statModel->setAttr('version', $statInfo['stat_date_max']);
        $this->statModel->setAttr('cost', floatval($statInfo['cost_sum']));
        if (! $this->statModel->save()) {
            return self::setError('更新统计数据失败');
        }

        return AccountLogService::deleteLog($this->syncModel, $statInfo['stat_date_max']);
    }

    public function delLog(array $where = []): bool
    {
        return true;
        /*dump($this->statModelList[CdcEnum::STAT_ACCOUNT]);exit;
        $obj = new $this->statModelList[CdcEnum::STAT_ACCOUNT]();
        return $obj->where($where)->delete() <= 0;*/
    }

    /*
    * 比较版本.
    * @param Model $model 中间表模型
    */
    protected function compareStat(): int
    {
        if (! $this->statModel->getKey()) {
            return -1;
        }

        return $this->statModel->getAttr('version') < $this->syncModel->getAttr('stat_date') ? 1 : -1;
    }

    /**
     * 获取汇总字段.
     */
    protected function getStatField(): array
    {
        $fields = $this->statModel->getNeedField();
        $data = [];
        foreach ($fields as $v) {
            if ($v == 'version') {
                $data[$v] = $this->recordModel->getAttr('stat_date');
            } else {
                $data[$v] = $this->recordModel->getAttr($v);
            }
        }
        return $data;
    }

    /**
     * 获取和汇总字段.
     */
    protected function getSumStatField(): array
    {
        $fields = $this->statModel->getSumField();
        $data = [];

        foreach ($fields as $v) {
            $data[$v] = $this->recordModel->getAttr($v);
        }

        return $data;
    }

    protected function getStatInfo(): array
    {
        $statDateMax = $this->recordModel->where($this->getSumStatField())->max('stat_date');
        $costSum = $this->recordModel->where($this->getSumStatField())->sum('cost');
        if (isset($statDateMax, $costSum)) {
            return ['stat_date_max' => $statDateMax, 'cost_sum' => $costSum];
        }
        return [];
    }
}
